package com.imdroid.carac.audioCodec;

import java.util.LinkedList;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

import com.imdroid.carac.activities.TeamMapActivity;

import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
import android.util.Log;

public class UDPSpeaker {
	private static AudioTrack audioPlayer;

	private static ExecutorService playService;
	private static Future<Void> playTask;
	static PlayTask play;

	private static volatile boolean shouldPause = false;

	private static volatile boolean mute = false;

	public static void addData(int user, byte[] audio) {
		if (isMute()) {
			return;
		}

		AudioPack pack = new AudioPack();
		pack.audio = audio;
		pack.user = user;
		play.audioBuffer.add(pack);
	}

	public static void setMute(boolean isMute) {
		mute = isMute;
	}

	public static boolean isMute() {
		return mute;
	}

	private static void play(AudioPack pack) {
		System.out.println("playing ... play ");
		if (audioPlayer == null) {
			audioPlayer = new AudioTrack(AudioManager.STREAM_MUSIC,
					C.samplesPerSec, AudioFormat.CHANNEL_OUT_MONO,
					AudioFormat.ENCODING_PCM_16BIT,
					AudioTrack.getMinBufferSize(C.samplesPerSec,
							AudioFormat.CHANNEL_OUT_MONO,
							AudioFormat.ENCODING_PCM_16BIT),
					AudioTrack.MODE_STREAM);
			audioPlayer.play();
		}
		byte[] playPcm = new byte[C.decPcm.capacity()];
		C.decStream.clear();
		C.decStream.put(pack.audio);
		int pcmSamples = C.dec(pack.audio.length);
		System.out.println("playing ... play " + pcmSamples);
		if (pcmSamples < 0)
			throw new RuntimeException("PCM Samples -> " + pcmSamples);
		if (pcmSamples == 0)
			return;
		int pcmBytes = 2 * pcmSamples;
		if (pcmBytes > C.decPcm.capacity()) {
			Log.w("Audio Play Back ", "Decode: stream too long " + pcmBytes);
			pcmBytes = C.decPcm.capacity();
		}
		C.decPcm.clear();
		C.decPcm.get(playPcm, 0, pcmBytes);
		audioPlayer.write(playPcm, 0, pcmBytes);
	}

	public static void start() {
		C.decReset();
		// ...
		playService = Executors.newFixedThreadPool(3);
		play = new PlayTask();
		playTask = playService.submit(play);
	}

	static class PlayTask implements Callable<Void> {

		private LinkedList<AudioPack> audioBuffer = new LinkedList<AudioPack>();

		@Override
		public Void call() throws Exception {
			while (true) {
				while (audioBuffer.size() <= 0 || shouldPause) {
					Thread.sleep(20);
				}

				AudioPack pack = audioBuffer.remove(0);
				play(pack);
			}
		}

	}

	public static void resume() {
		shouldPause = false;
	}

	public static void pause() {
		shouldPause = true;
	}

	public static void stop() {
		if (playTask != null) {
			playTask.cancel(true);
			playTask = null;
		}
		if (playService != null) {
			playService.shutdown();
		}
		if (audioPlayer != null) {
			audioPlayer.stop();
			audioPlayer.release();
			audioPlayer = null;
		}
	}

	private static class AudioPack {
		private byte[] audio;
		@SuppressWarnings("unused")
		private int user;
	}
}
